package com.mfs.proxy.server;


import com.alibaba.fastjson2.JSON;
import com.mfs.common.utills.TaskUtil;
import com.mfs.proxy.core.server.config.ServerConfig;
import com.mfs.proxy.core.server.reactor.ProxyReactor;
import com.mfs.proxy.core.server.reactor.ServerReactor;
import com.mfs.proxy.core.server.reactor.SubProxyReactor;
import com.mfs.proxy.core.server.reactor.SubServerReactor;
import com.mfs.proxy.server.httpclient.ProxyManagerClient;
import com.mfs.proxy.server.httpclient.dto.ServerRegisterRequest;
import com.mfs.proxy.server.httpclient.dto.ServerRegisterResponse;
import com.mfs.proxy.server.httpclient.dto.ServerUnregisterRequest;
import com.mfs.proxy.server.httpclient.dto.ServerUnregisterResponse;
import feign.Feign;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

/**
 * 代理服务端启动类
 * @author mfs
 * @date 2023-07-30
 * */
public class ReverseProxyServer {
    private static final Logger logger = LoggerFactory.getLogger(ReverseProxyServer.class);
    public static void main(String[] args) {
        registerServer();
        startServerTask();
        startProxyTask();
        logger.info("代理服务端启动成功");
    }

    /**
     * 如果开启管理端，则向管理端注册代理服务器信息
     * 除此之外还要注册shutdown钩子，当代理服务端终止时向管理端注销代理服务器
     * */
    private static void registerServer() {
        ServerConfig serverConfig = ServerConfig.getInstance();
        if (serverConfig.getManagerEnable()) {
            // 注册代理服务器
            ServerRegisterRequest registerRequest = ServerRegisterRequest.builder()
                    .outIp(serverConfig.getProxyIp())
                    .ip(serverConfig.getServerIp()).build();
            ServerRegisterResponse registerResponse = Feign.builder()
                    .decoder(new GsonDecoder())
                    .encoder(new GsonEncoder())
                    .target(ProxyManagerClient.class, serverConfig.getManagerUrl())
                    .serverRegister(registerRequest);
            if (registerResponse == null || !Objects.equals(registerResponse.getErrorNo(), 0)) {
                throw new RuntimeException(registerResponse == null ? "连接管理端失败" : registerResponse.getErrorInfo());
            }

            // 注册钩子
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                ServerUnregisterRequest unregisterRequest = ServerUnregisterRequest.builder()
                        .outIp(serverConfig.getProxyIp())
                        .ip(serverConfig.getServerIp()).build();
                ServerUnregisterResponse unregisterResponse = Feign.builder()
                        .decoder(new GsonDecoder())
                        .encoder(new GsonEncoder())
                        .target(ProxyManagerClient.class, serverConfig.getManagerUrl())
                        .serverUnregister(unregisterRequest);
                logger.info("注销代理服务器完成：{}", JSON.toJSONString(unregisterResponse));
            }));
        }
    }

    /**
     * 启动服务端服务 reactor
     * */
    private static void startServerTask() {
        TaskUtil.start(new ServerReactor(ServerConfig.getInstance().getServerIp(), ServerConfig.getInstance().getServerPort()));
        TaskUtil.daemonStart(new SubServerReactor());
        logger.info("启动客户端接入点成功，接入地址：{}:{}", ServerConfig.getInstance().getServerIp(), ServerConfig.getInstance().getServerPort());
    }

    /**
     * 启动代理 reactor
     * */
    private static void startProxyTask() {
        TaskUtil.daemonStart(new ProxyReactor());
        TaskUtil.daemonStart(new SubProxyReactor());
        logger.info("启动代理接入点成功");
    }

}
